From 268a6ca5d949ff9e8ce79cbe78cd3892ae2f6183 Mon Sep 17 00:00:00 2001 From: =?utf8?q?=C3=98yvind=20Kol=C3=A5s?= Date: Sun, 18 Sep 2005 22:33:16 +0000 Subject: [PATCH] adding gggl extension --- ChangeLog | 7 + extensions/gggl.c | 1946 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 1953 insertions(+) create mode 100644 extensions/gggl.c diff --git a/ChangeLog b/ChangeLog index cf5c7e9..c421930 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2005-09-19 Øyvind Kolås + + * extensions/gggl.c: Added the bulk of gggl based conversions as an + extension. Many of these don't live up to the quality requirements of + babl, but some do, and provide a good base for further BablFishPath + coverage. + 2005-09-18 Øyvind Kolås * docs/tools/changelog2rss: tool to create RSS feed of ChangeLog. diff --git a/extensions/gggl.c b/extensions/gggl.c new file mode 100644 index 0000000..a598de1 --- /dev/null +++ b/extensions/gggl.c @@ -0,0 +1,1946 @@ +/* + * This file was part of gggl, it implements a variety of pixel conversion + * functions that are usable with babl, the file needs more cleanup, and + * doesn't return the number of samples processed as a long, like it's supposed to. + * + * GGGL is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * GGGL is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GGGL; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * Rights are granted to use this shared object in libraries covered by + * LGPL. (exception added, during import into babl CVS.) + * + * Copyright 2003, 2004, 2005 Øyvind Kolås + */ + +#include "babl.h" + +#define INLINE inline + +#include +#include +#include + +/* + * Implemented according to information read from: + * + * http://www.cinenet.net/~spitzak/conversion/sketches_0265.pdf + * + * initially ignoring any diffusion, to keep the implementation + * smaller, and interchangeable with the non optimized version. + * + * due to ability to be able to relicence gggl under a different + * licence than GPL, I avoided the temptation to look at the + * source files in the same location, in case I was going to + * need this piece of code for projects where GPL compatibility + * was a must. + * + * TODO: error diffusion, + * gamma correction (not really,. gamma correction belongs in seperate ops,. + */ + +#define USE_TABLES +#ifdef USE_TABLES + +/* lookup tables used in conversion */ + +static float table_8_F[1 << 8]; +static float table_16_F[1 << 16]; +static unsigned char table_F_8[1 << 16]; +static unsigned short table_F_16[1 << 16]; + + +static int table_inited = 0; + +static void +table_init (void) +{ + if (table_inited) + return; + table_inited = 1; + + /* fill tables for conversion from integer to float */ + { + int i; + for (i = 0; i < 1 << 8; i++) + { + table_8_F[i] = (i * 1.0) / 255.0; + } + for (i = 0; i < 1 << 16; i++) + table_16_F[i] = (i * 1.0) / 65535.0; + } + /* fill tables for conversion from float to integer */ + { + union + { + float f; + unsigned short s[2]; + } u; + u.f = 0.0; + + u.s[0] = 0.0; + + for (u.s[1] = 0; u.s[1] < 65535; u.s[1] += 1) + { + unsigned char c; + unsigned short s; + + if (u.f <= 0.0) + { + c = 0; + s = 0; + } + else if (u.f >= 1.0) + { + c = 255; + s = 65535; + } + else + { + c = rint (u.f * 255.0); + s = rint (u.f * 65535.0); + } + + /*fprintf (stderr, "%2.3f=%03i %05i ", f, c, (*hi)); + / if (! ((*hi)%9)) + / fprintf (stderr, "\n"); */ + + table_F_8[u.s[1]] = c; + table_F_16[u.s[1]] = s; + } + } + /* fix tables to ensure 1:1 conversions back and forth */ + if (0) + { /*FIXME: probably not the right way to do it,.. must sit down and scribble on paper */ + int i; + for (i = 0; i < 256; i++) + { + float f = table_8_F[i]; + unsigned short *hi = ((unsigned short *) &f); + unsigned short *lo = ((unsigned short *) &f); + *lo = 0; + table_F_8[(*hi)] = i; + } + } +} + +/* function to find the index in table for a float */ +static unsigned int +gggl_float_to_index16 (float f) +{ + union + { + float f; + unsigned short s[2]; + } u; + u.f = f; + return u.s[1]; +} + + +static INLINE long +conv_F_8 (unsigned char *src, unsigned char *dst, long samples) +{ + if (!table_inited) + table_init (); + long n=samples; + while (n--) + { + register float f = (*(float *) src); + *(unsigned char *) dst = table_F_8[gggl_float_to_index16 (f)]; + dst += 1; + src += 4; + } + return samples; +} + +static INLINE long +conv_F_16 (unsigned char *src, unsigned char *dst, long samples) +{ + if (!table_inited) + table_init (); + long n=samples; + while (n--) + { + register float f = (*(float *) src); + *(unsigned short *) dst = table_F_16[gggl_float_to_index16 (f)]; + dst += 2; + src += 4; + } + return samples; +} + +static INLINE long +conv_8_F (unsigned char *src, unsigned char *dst, long samples) +{ + if (!table_inited) + table_init (); + long n=samples; + while (n--) + { + (*(float *) dst) = table_8_F[*(unsigned char *) src]; + dst += 4; + src += 1; + } + return samples; +} + +static INLINE long +conv_16_F (unsigned char *src, unsigned char *dst, long samples) +{ + if (!table_inited) + table_init (); + long n=samples; + while (n--) + { + (*(float *) dst) = table_16_F[*(unsigned short *) src]; + dst += 4; + src += 2; + } + return samples; +} + +#else + +static INLINE long +conv_F_8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + float f = ((*(float *) src)); + if (f < 0.0) + { + *(unsigned char *) dst = 0; + } + else if (f > 1.0) + { + *(unsigned char *) dst = 255; + } + else + { + *(unsigned char *) dst = rint (f * 255.0); + } + dst += 1; + src += 4; + } + return samples; +} + +static INLINE long +conv_F_16 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + float f = ((*(float *) src)); + if (f < 0.0) + { + *(unsigned short *) dst = 0; + } + else if (f > 1.0) + { + *(unsigned short *) dst = 65535; + } + else + { + *(unsigned short *) dst = rint (f * 65535.0); + } + dst += 2; + src += 4; + } + return samples; +} + +static INLINE long +conv_8_F (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + (*(float *) dst) = (*(unsigned char *) src / 255.0); + dst += 4; + src += 1; + } + return samples; +} + +static INLINE long +conv_16_F (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + (*(float *) dst) = *(unsigned short *) src / 65535.0; + dst += 4; + src += 2; + } + return samples; +} + + +#endif + +static INLINE long +conv_16_8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + (*(unsigned char *) dst) = (*(unsigned short *) src) >> 8; + dst += 1; + src += 2; + } + return samples; +} + +static INLINE long +conv_8_16 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + (*(unsigned short *) dst) = (*(unsigned char *) src) << 8; + dst += 2; + src += 1; + } + return samples; +} + +/*********/ +static INLINE long +conv_rgbaF_rgba8 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_8 (src, dst, samples * 4); + return samples; +} + +#define conv_rgbaF_rgbP8 conv_rgbaF_rgba8 + +static INLINE long +conv_rgbF_rgb8 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_8 (src, dst, samples * 3); + return samples; +} + +static INLINE long +conv_gaF_ga8 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_8 (src, dst, samples * 2); + return samples; +} + +#define conv_rgbAF_rgbA8 conv_rgbaF_rgba8 +#define conv_gF_g8 conv_F_8 +#define conv_gAF_gA8 conv_gaF_ga8 + +static INLINE long +conv_rgbaF_rgba16 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_16 (src, dst, samples * 4); + return samples; +} + +static INLINE long +conv_rgbF_rgb16 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_16 (src, dst, samples * 3); + return samples; +} + +static INLINE long +conv_gaF_ga16 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_F_16 (src, dst, samples * 2); + return samples; +} + +#define conv_rgbAF_rgbA16 conv_rgbaF_rgba16 +#define conv_gF_g16 conv_F_16 +#define conv_gAF_gA16 conv_gaF_ga16 + +static INLINE long +conv_rgba8_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_8_F (src, dst, samples * 4); + return samples; +} + +static INLINE long +conv_rgb8_rgbF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_8_F (src, dst, samples * 3); + return samples; +} + +static INLINE long +conv_ga8_gaF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_8_F (src, dst, samples * 2); + return samples; +} + +#define conv_rgbA8_rgbAF conv_rgba8_rgbaF +#define conv_gA8_gAF conv_ga8_gaF +#define conv_g8_gF conv_8_F + +static INLINE long +conv_rgba16_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_16_F (src, dst, samples * 4); + return samples; +} + +static INLINE long +conv_rgb16_rgbF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_16_F (src, dst, samples * 3); + return samples; +} + +static INLINE long +conv_ga16_gaF (unsigned char *src, unsigned char *dst, long samples) +{ + conv_16_F (src, dst, samples * 2); + return samples; +} + +#define conv_rgbA16_rgbAF conv_rgba16_rgbaF +#define conv_gA16_gAF conv_ga16_gaF +#define conv_g16_gF conv_16_F + +static INLINE long +conv_rgba16_rgba8 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_16_8 (src, dst, samples * 4); + return samples; +} + +static INLINE long +conv_rgb16_rgb8 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_16_8 (src, dst, samples * 3); + return samples; +} + +static INLINE long +conv_ga16_ga8 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_16_8 (src, dst, samples * 2); + return samples; +} + +#define conv_rgbA16_rgbA8 conv_rgba16_rgba8 +#define conv_gA16_gA8 conv_ga16_ga8 +#define conv_g16_g8 conv_16_8 + +static INLINE long +conv_rgba8_rgba16 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_8_16 (src, dst, samples * 4); + return samples; +} + +static INLINE long +conv_rgb8_rgb16 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_8_16 (src, dst, samples * 3); + return samples; +} + +static INLINE long +conv_ga8_ga16 (unsigned char *src, unsigned char *dst, long samples) +{ + conv_8_16 (src, dst, samples * 2); + return samples; +} + +#define conv_rgbA8_rgbA16 conv_rgba8_rgba16 +#define conv_gA8_gA16 conv_ga8_ga16 +#define conv_g8_g16 conv_8_16 + +/* alpha conversions */ + +static INLINE long +conv_gaF_gAF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + float alpha = (*(float *) (src + 4)); + + *(float *) dst = ((*(float *) src) * alpha); + dst += 4; + src += 4; + *(float *) dst = alpha; + dst += 4; + src += 4; + } + return samples; +} + +static INLINE long +conv_gAF_gaF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + float alpha = (*(float *) (src + 4)); + + *(float *) dst = ((*(float *) src) / alpha); + dst += 4; + src += 4; + *(float *) dst = alpha; + dst += 4; + src += 4; + } + return samples; +} + +static INLINE long +conv_rgbAF_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + float alpha = (*(float *) (src + 4 * 3)); + int c; + if (alpha >= 1.0) + { + for (c = 0; c < 3; c++) + { + *(float *) dst = *(float *) src; + dst += 4; + src += 4; + } + } + else if (alpha <= 0.0) + { + for (c = 0; c < 3; c++) + { + *(float *) dst = 0; + dst += 4; + src += 4; + } + } + else + { + for (c = 0; c < 3; c++) + { + *(float *) dst = ((*(float *) src) / alpha); + dst += 4; + src += 4; + } + } + *(float *) dst = alpha; + dst += 4; + src += 4; + } + return samples; +} + +static INLINE long +conv_rgbaF_rgbAF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + float alpha = (*(float *) (src + 4 * 3)); + int c; + + if (alpha >= 1.0) + { + for (c = 0; c < 3; c++) + { + *(float *) dst = *(float *) src; + dst += 4; + src += 4; + } + } + else if (alpha <= 0.0) + { + for (c = 0; c < 3; c++) + { + *(float *) dst = 0; + dst += 4; + src += 4; + } + } + else + { + for (c = 0; c < 3; c++) + { + *(float *) dst = ((*(float *) src) * alpha); + dst += 4; + src += 4; + } + } + *(float *) dst = alpha; + dst += 4; + src += 4; + } + return samples; +} + +/* alpha stripping and adding */ + +static INLINE long +conv_rgbaF_rgbF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + *(int *) dst = (*(int *) src); + dst += 4; + src += 4; + *(int *) dst = (*(int *) src); + dst += 4; + src += 4; + *(int *) dst = (*(int *) src); + dst += 4; + src += 4; + src += 4; + } + return samples; +} + +static INLINE long +conv_rgbF_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + *(int *) dst = (*(int *) src); + dst += 4; + src += 4; + *(int *) dst = (*(int *) src); + dst += 4; + src += 4; + *(int *) dst = (*(int *) src); + dst += 4; + src += 4; + *(float *) dst = 1.0; + dst += 4; + } + return samples; +} + +static INLINE long +conv_gaF_gF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + *(int *) dst = (*(int *) src); + dst += 4; + src += 4; + src += 4; + } + return samples; +} + +static INLINE long +conv_gF_gaF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + *(int *) dst = (*(int *) src); + dst += 4; + src += 4; + *(float *) dst = 1.0; + dst += 4; + } + return samples; +} + +#define conv_gAF_gF conv_gaF_gF +#define conv_gF_gAF conv_gF_gaF + +#define conv_rgbAF_rgbF conv_rgbaF_rgbF +#define conv_rgbF_rgbAF conv_rgbF_rgbaF + +/* colorchannel dropping and adding */ + +static INLINE long +conv_gF_rgbF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + int c; + + for (c = 0; c < 3; c++) + { + (*(int *) dst) = (*(int *) src); + dst += 4; + } + src += 4; + } + return samples; +} + +static INLINE long +conv_rgbF_gF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + int c; + float sum = 0; + + for (c = 0; c < 3; c++) + { + sum += (*(float *) src); + src += 4; + } + sum /= 3; + (*(float *) dst) = sum; + dst += 4; + } + return samples; +} + +static INLINE long +conv_gaF_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + int c; + + for (c = 0; c < 3; c++) + { + (*(int *) dst) = (*(int *) src); + dst += 4; + } + src += 4; + (*(int *) dst) = (*(int *) src); + dst += 4; + src += 4; + } + return samples; +} + +static INLINE long +conv_rgbaF_gaF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + int c; + float sum = 0; + + for (c = 0; c < 3; c++) + { + sum += (*(float *) src); + src += 4; + } + (*(float *) dst) = sum / 3; + dst += 4; + (*(int *) dst) = (*(int *) src); + dst += 4; + src += 4; + + } + return samples; +} + +#define conv_gAF_rgbAF conv_gaF_rgbaF +#define conv_rgbAF_gAF conv_rgbaF_gaF + +/* other conversions coded for some optimisation reason or sumthin */ + +static INLINE long +conv_rgbA8_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + float alpha = (*(unsigned char *) src + (3)) / 255.0; + int c; + + for (c = 0; c < 3; c++) + { + (*(float *) dst) = (*(unsigned char *) src / 255.0) / alpha; + dst += 4; + src += 1; + } + *(float *) dst = alpha; + dst += 4; + src += 1; + } + return samples; +} + +static INLINE long +conv_rgbaF_rgbA8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + float alpha = (*(float *) (src + (4 * 3))); + int c; + + for (c = 0; c < 3; c++) + { + *(unsigned char *) dst = ((*(float *) src) * alpha) * 255.0; + dst += 1; + src += 4; + } + *(unsigned char *) dst = alpha * 255.0; + dst++; + src += 4; + } + return samples; +} + +static INLINE long +conv_rgbaF_rgbA16 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + float alpha = (*(float *) src + (4 * 3)); + int c; + + for (c = 0; c < 3; c++) + { + *(unsigned short *) dst = ((*(float *) src) * alpha) * 65535.0; + dst += 2; + src += 4; + } + *(unsigned short *) dst = alpha * 65535.0; + dst += 2; + src += 4; + } + return samples; +} + +static INLINE long +conv_rgbaF_rgb8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + int c; + + for (c = 0; c < 3; c++) + { + *(unsigned char *) dst = (*(float *) src) * 255.0; + dst += 1; + src += 4; + } + src += 4; + } + return samples; +} + +static INLINE long +conv_rgbaF_g8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + int c; + float sum = 0; + + for (c = 0; c < 3; c++) + { + sum += (*(float *) src); + src += 4; + } + *(unsigned char *) dst = sum * 255.0 / 3; + dst++; + src += 4; + } + return samples; +} + +static INLINE long +conv_rgbaF_rgb16 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + int c; + + for (c = 0; c < 3; c++) + { + *(unsigned short *) dst = (*(float *) src) * 65535.0; + dst += 2; + src += 4; + } + src += 4; + } + return samples; +} + +static INLINE long +conv_rgbP8_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + int c; + + for (c = 0; c < 3; c++) + { + (*(float *) dst) = *(unsigned char *) src / 255.0; + dst += 4; + src += 1; + } + (*(float *) dst) = 1.0; + dst += 4; + src += 1; + } + return samples; +} + +static INLINE long +conv_rgbA16_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + float alpha = (*(unsigned short *) src + (3)) / 65535.0; + int c; + + for (c = 0; c < 3; c++) + { + (*(float *) dst) = (*(unsigned short *) src / 65535.0) / alpha; + dst += 4; + src += 2; + } + *(float *) dst = alpha; + dst += 4; + src += 2; + } + return samples; +} + +/* +static INLINE long +conv_rgb8_rgbaF (unsigned char *src, + unsigned char *dst, + int samples) +{ + long n=samples; + while (n--) { + int c; + + for (c = 0; c < 3; c++) { + (*(float *) dst) = *(unsigned char *) src / 255.0; + dst += 4; + src += 1; + } + (*(float *) dst) = 1.0; + dst += 4; + } + return samples; +} + +static INLINE long +conv_g8_rgbaF (unsigned char *src, + unsigned char *dst, + int samples) +{ + long n=samples; + while (n--) { + int c; + + for (c = 0; c < 3; c++) { + (*(float *) dst) = *(unsigned char *) src / 255.0; + dst += 4; + } + src += 1; + (*(float *) dst) = 1.0; + dst += 4; + } + return samples; +} + +static INLINE long +conv_rgb16_rgbaF (unsigned char *src, + unsigned char *dst, + int samples) +{ + long n=samples; + while (n--) { + int c; + + for (c = 0; c < 3; c++) { + *(float *) dst = (*(unsigned short *) src) / 65535.0; + src += 2; + dst += 4; + } + *(float *) dst = 1.0; + src += 2; + dst += 4; + } + return samples; +} + +static INLINE long +conv_gF_rgbaF (unsigned char *src, + unsigned char *dst, + int samples) +{ + long n=samples; + while (n--) { + (*(float *) dst) = (*(float *) src); + dst += 4; + (*(float *) dst) = (*(float *) src); + dst += 4; + (*(float *) dst) = (*(float *) src); + dst += 4; + (*(float *) dst) = 1.0; + dst += 4; + src += 4; + + } + return samples; +} +*/ +static INLINE long +conv_rgba8_rgbA8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + if (src[3] == 255) + { + *(unsigned int *) dst = *(unsigned int *) src; + } + else if (src[3] == 0) + { + *(unsigned int *) dst = 0; + } + else + { + dst[0] = (src[0] * src[3]) >> 8; /* FIXME: check if this faster */ + dst[1] = (src[1] * src[3]) >> 8; /* version (>>8 vs /255) */ + dst[2] = (src[2] * src[3]) >> 8; /* is accurate enough */ + dst[3] = src[3]; + } + dst += 4; + src += 4; + } + return samples; +} + +static INLINE long +conv_rgbA8_rgba8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + if (src[3] == 255) + { + *(unsigned int *) dst = *(unsigned int *) src; + dst += 4; + } + else if (src[3] == 0) + { + *(unsigned int *) dst = 0; + dst += 4; + } + else + { + unsigned int aa = (255 << 16) / src[3]; + *dst++ = (src[0] * aa) >> 16; + *dst++ = (src[1] * aa) >> 16; + *dst++ = (src[2] * aa) >> 16; + *dst++ = src[3]; + } + src += 4; + } + return samples; +} + +static INLINE long +conv_argb8_rgba8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = src[3]; + src += 4; + dst += 4; + } + return samples; +} + +static INLINE long +conv_rgba8_argb8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + dst[0] = src[3]; + dst[1] = src[0]; + dst[2] = src[1]; + dst[3] = src[2]; + src += 4; + dst += 4; + } + return samples; +} + +static INLINE long +conv_Argb8_rgbA8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = src[3]; + src += 4; + dst += 4; + } + return samples; +} + +static INLINE long +conv_rgbA8_Argb8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = src[3]; + src += 4; + dst += 4; + } + return samples; +} + +static INLINE long +conv_Prgb8_rgbP8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = 255; + src += 4; + dst += 4; + } + return samples; +} + +static INLINE long +conv_rgbP8_Prgb8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + dst[3] = 255; + src += 4; + dst += 4; + } + return samples; +} + +static INLINE long +conv_Prgb8_rgb8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + dst[0] = src[2]; + dst[1] = src[1]; + dst[2] = src[0]; + /*dst[3] = src[3]; */ + src += 4; + dst += 3; + } + return samples; +} + + +/* FIXME: this is actually BGRP */ +static INLINE long +conv_rgb8_Prgb8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + dst[0] = src[2]; /* blue */ + dst[1] = src[1]; /* green */ + dst[2] = src[0]; /* red */ + dst[3] = 255; + src += 3; + dst += 4; + } + return samples; +} + +static INLINE long +conv_rgbA16_rgba16 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + if (src[3]) + { + ((unsigned short *) dst)[0] = + (((unsigned short *) src)[0] * 65535) / src[3]; + ((unsigned short *) dst)[1] = + (((unsigned short *) src)[1] * 65535) / src[3]; + ((unsigned short *) dst)[2] = + (((unsigned short *) src)[2] * 65535) / src[3]; + } + ((unsigned short *) dst)[3] = ((unsigned short *) src)[3]; + dst += 8; + src += 8; + } + return samples; +} + +static INLINE long +conv_rgb8_rgbP8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + src += 3; + dst += 4; + } + return samples; +} + +static INLINE long +conv_rgb8_rgba8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + *(unsigned int *) dst = *(unsigned int *) src; + dst[3] = 255; + src += 3; + dst += 4; + } + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + dst[3] = 255; + return samples; +} + +#define conv_rgb8_rgbA8 conv_rgb8_rgba8 + +static INLINE long +conv_rgbP8_rgba8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + *(unsigned int *) dst = *(unsigned int *) src; + dst[3] = 255; + src += 4; + dst += 4; + } + return samples; +} + +#define conv_rgbP8_rgbA8 conv_rgbP8_rgba8 + +static INLINE long +conv_rgba8_rgbP8 (unsigned char *src, unsigned char *dst, long samples) +{ + memcpy (dst, src, samples * 4); + return samples; +} + +#define conv_rgbA8_rgbP8 conv_rgba8_rgbP8 + +static INLINE long +conv_rgbP8_rgb8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + src += 4; + dst += 3; + } + return samples; +} + +static INLINE long +conv_rgba8_rgb8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + dst[0] = src[0]; + dst[1] = src[1]; + dst[2] = src[2]; + src += 4; + dst += 3; + } + return samples; +} + +#define conv_rgbA8_rgb8 conv_rgbP8_rgb8 + +#ifndef byteclamp +#define byteclamp(j) do{if(j<0)j=0; else if(j>255)j=255;}while(0) +#endif + +#define YUV82RGB8(Y,U,V,R,G,B)do{\ + R= ((Y<<15) + 37355*(V-128))>>15;\ + G= ((Y<<15) -12911* (U-128) - 19038*(V-128))>>15;\ + B= ((Y<<15) +66454* (U-128) )>>15;\ + byteclamp(R);\ + byteclamp(G);\ + byteclamp(B);\ +}while(0) + +#define RGB82YUV8(R,G,B,Y,U,V)do{\ + Y= (( 9798*R + 19234*G + 3736*B)>>15) +000;\ + U= ((-4817*R - 9470*G + 14320*B)>>15) +128;\ + V= (( 20152*R - 16875*G - 3277*B)>>15) +128;\ + byteclamp(Y);\ + byteclamp(U);\ + byteclamp(V);\ +}while(0) + +static INLINE long +conv_yuv8_rgb8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + int R, G, B; + + YUV82RGB8 (src[0], src[1], src[2], R, G, B); + dst[0] = R; + dst[1] = G; + dst[2] = B; + src += 3; + dst += 3; + } + return samples; +} + +static INLINE long +conv_rgb8_yuv8 (unsigned char *src, unsigned char *dst, long samples) +{ + long n=samples; + while (n--) + { + int Y, U, V; + + YUV82RGB8 (src[0], src[1], src[2], Y, U, V); + dst[0] = Y; + dst[1] = U; + dst[2] = V; + src += 3; + dst += 3; + } + return samples; +} + +static INLINE long +conv_rgbaF_yuvaF (unsigned char *src, unsigned char *dst, long samples) +{ + float *src_f = (float *) src; + float *dst_f = (float *) dst; + long n=samples; + while (n--) + { + float R, G, B; + float Y, U, V; + + R = src_f[0]; + G = src_f[1]; + B = src_f[2]; + + Y = 0.299 * R + 0.587 * B + 0.114 * B; + U = (-0.1687) * R - 0.3313 * G + 0.5 * B /* +0.5 */ ; + V = 0.5 * R - 0.4187 * G - 0.0813 * B /* +0.5 */ ; + + dst_f[0] = Y; + dst_f[1] = U; + dst_f[2] = V; + dst_f[3] = src_f[3]; + + dst_f += 4; + src_f += 4; + } + return samples; +} + +static INLINE long +conv_yuvaF_rgbaF (unsigned char *src, unsigned char *dst, long samples) +{ + float *src_f = (float *) src; + float *dst_f = (float *) dst; + long n=samples; + while (n--) + { + float Y, U, V; + float R, G, B; + + Y = src_f[0]; + U = src_f[1]; + V = src_f[2]; + + R = Y + 1.40200 * (V /*-0.5*/ ); + G = Y - 0.34414 * (U /*-0.5*/ ) - 0.71414 * (V /*-0.5*/ ); + B = Y + 1.77200 * (U /*-0.5*/ ); + + dst_f[0] = R; + dst_f[1] = G; + dst_f[2] = B; + dst_f[3] = src_f[3]; + + dst_f += 4; + src_f += 4; + } + return samples; +} + + + +static INLINE long +conv_rgbF_yuvF (unsigned char *src, unsigned char *dst, long samples) +{ + float *src_f = (float *) src; + float *dst_f = (float *) dst; + long n=samples; + while (n--) + { + float R, G, B; + float Y, U, V; + + R = src_f[0]; + G = src_f[1]; + B = src_f[2]; + + Y = 0.299 * R + 0.587 * B + 0.114 * B; + U = (-0.1687) * R - 0.3313 * G + 0.5 * B /* +0.5 */ ; + V = 0.5 * R - 0.4187 * G - 0.0813 * B /* +0.5 */ ; + + dst_f[0] = Y; + dst_f[1] = U; + dst_f[2] = V; + + dst_f += 3; + src_f += 3; + } + return samples; +} + +static INLINE long +conv_yuvF_rgbF (unsigned char *src, unsigned char *dst, long samples) +{ + float *src_f = (float *) src; + float *dst_f = (float *) dst; + long n=samples; + while (n--) + { + float Y, U, V; + float R, G, B; + + Y = src_f[0]; + U = src_f[1]; + V = src_f[2]; + + R = Y + 1.40200 * (V /*-0.5*/ ); + G = Y - 0.34414 * (U /*-0.5*/ ) - 0.71414 * (V /*-0.5*/ ); + B = Y + 1.77200 * (U /*-0.5*/ ); + + dst_f[0] = R; + dst_f[1] = G; + dst_f[2] = B; + + dst_f += 3; + src_f += 3; + } + return samples; +} + + +/******* lab, xyz and rgb interaction, lifted from cpercep by adam d. moss */ + +#include + +/* +static const double Xn = 0.951; +static const double Yn = 1.0; +static const double Zn = 1.089; +*/ + +#define LXN 0.312713F +#define LYN 0.329016F + +static const double lxn = LXN; +static const double lyn = LYN; +static double xnn = LXN / LYN; +static double znn = (1.0F - (LXN + LYN)) / LYN; + + +static const double LRAMP = 7.99959199F; + +static INLINE long +conv_rgbF_xyzF (unsigned char *src, unsigned char *dst, long samples) +{ + float *src_f = (float *) src; + float *dst_f = (float *) dst; + long n=samples; + while (n--) + { + float x, y, z; + float red, green, blue; + + red = src_f[0]; + green = src_f[1]; + blue = src_f[2]; + + x = 0.431 * red + 0.342 * green + 0.179 * blue; + y = 0.222 * red + 0.707 * green + 0.071 * blue; + z = 0.020 * red + 0.130 * green + 0.939 * blue; + + dst_f[0] = x; + dst_f[1] = y; + dst_f[2] = z; + dst_f += 3; + src_f += 3; + } + return samples; +} + +static INLINE long +conv_xyzF_rgbF (unsigned char *src, unsigned char *dst, long samples) +{ + float *src_f = (float *) src; + float *dst_f = (float *) dst; + long n=samples; + while (n--) + { + dst_f[0] = src_f[0]; + dst_f[1] = src_f[1]; + dst_f[2] = src_f[2]; + dst_f += 3; + src_f += 3; + } + return samples; +} + +static INLINE double +ffunc (const double t) +{ + if (t > 0.008856F) + { + return (cbrt (t)); + } + else + { + return (7.787F * t + 16.0F / 116.0F); + } +} + + +static INLINE double +ffunc_inv (const double t) +{ + if (t > 0.206893F) + { + return (t * t * t); + } + else + { + return ((t - 16.0F / 116.0F) / 7.787F); + } +} + +static INLINE long +conv_labF_xyzF (unsigned char *src, unsigned char *dst, long samples) +{ + float *src_f = (float *) src; + float *dst_f = (float *) dst; + long n=samples; + while (n--) + { + float P; + float X, Y, Z; + float L, a, b; + + L = src_f[0]; + a = src_f[1]; + b = src_f[2]; + + if (L > LRAMP) + { + P = Y = (L + 16.0F) / 116.0F; + Y = Y * Y * Y; + } + else + { + Y = L / 903.3F; + P = 7.787F * Y + 16.0F / 116.0F; + } + + X = (P + a / 500.0F); + X = xnn * ffunc_inv (X); + Z = (P - b / 200.0F); + Z = znn * ffunc_inv (Z); + + + dst_f[0] = X; + dst_f[1] = Y; + dst_f[2] = Z; + dst_f += 3; + src_f += 3; + } +} + +static INLINE long +conv_xyzF_labF (unsigned char *src, unsigned char *dst, long samples) +{ + float *src_f = (float *) src; + float *dst_f = (float *) dst; + long n=samples; + while (n--) + { + double ffuncY; + float X, Y, Z; + float L, a, b; + X = src_f[0]; + Y = src_f[1]; + Z = src_f[2]; + + if (Y > 0.0F) + { + if (Y > 0.008856F) + { + L = (116.0F * cbrt (Y)) - 16.0F; + } + else + { + L = (Y * 903.3F); + } + } + else + { + L = 0.0; + } + + ffuncY = ffunc (Y); + a = 500.0F * (ffunc (X / xnn) - ffuncY); + b = 200.0F * (ffuncY - ffunc (Z / znn)); + + dst_f[0] = L; + dst_f[1] = a; + dst_f[2] = b; + dst_f += 3; + src_f += 3; + } +} + +/******* end of cpercep lift out **/ + + +#define MAX_CONVERSIONS 100 + +typedef struct Conversion +{ + int from_fmt; + int to_fmt; + int cost; /* cost of function,. calculated as ms to convert 1024*1024 samples */ + int loss; /* 0 maps ok, 1 precision loss, 2 alpha loss, 4 channel loss + (should be dwelled further into) */ + void (*function) (unsigned char *src, unsigned char *dst, long samples); +} Conversion; + +int +init (void) +{ + Babl *rgbaF = babl_format_new ( + babl_model ("RGBA"), + babl_type ("float"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + Babl *rgba16 = babl_format_new ( + babl_model ("RGBA"), + babl_type ("u16"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + Babl *rgba8 = babl_format_new ( + babl_model ("RGBA"), + babl_type ("u8"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + babl_component ("A"), + NULL); + Babl *rgbAF = babl_format_new ( + babl_model ("RaGaBaA"), + babl_type ("float"), + babl_component ("Ra"), + babl_component ("Ga"), + babl_component ("Ba"), + babl_component ("A"), + NULL); + Babl *rgbA16 = babl_format_new ( + babl_model ("RaGaBaA"), + babl_type ("u16"), + babl_component ("Ra"), + babl_component ("Ga"), + babl_component ("Ba"), + babl_component ("A"), + NULL); + Babl *rgbA8 = babl_format_new ( + babl_model ("RaGaBaA"), + babl_type ("u8"), + babl_component ("Ra"), + babl_component ("Ga"), + babl_component ("Ba"), + babl_component ("A"), + NULL); + Babl *rgbF = babl_format_new ( + babl_model ("RGB"), + babl_type ("float"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + Babl *rgb16 = babl_format_new ( + babl_model ("RGB"), + babl_type ("u16"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + Babl *rgb8 = babl_format_new ( + babl_model ("RGB"), + babl_type ("u8"), + babl_component ("R"), + babl_component ("G"), + babl_component ("B"), + NULL); + Babl *gaF = babl_format_new ( + babl_model ("YA"), + babl_type ("float"), + babl_component ("Y"), + babl_component ("A"), + NULL); + Babl *gAF = babl_format_new ( + babl_model ("YaA"), + babl_type ("float"), + babl_component ("Ya"), + babl_component ("A"), + NULL); + Babl *gF = babl_format_new ( + babl_model ("Y"), + babl_type ("float"), + babl_component ("Y"), + NULL); + Babl *ga16 = babl_format_new ( + babl_model ("YA"), + babl_type ("u16"), + babl_component ("Y"), + babl_component ("A"), + NULL); + Babl *gA16 = babl_format_new ( + babl_model ("YaA"), + babl_type ("u16"), + babl_component ("Ya"), + babl_component ("A"), + NULL); + Babl *g16 = babl_format_new ( + babl_model ("Y"), + babl_type ("u16"), + babl_component ("Y"), + NULL); + Babl *ga8 = babl_format_new ( + babl_model ("YA"), + babl_type ("u8"), + babl_component ("Y"), + babl_component ("A"), + NULL); + Babl *gA8 = babl_format_new ( + babl_model ("YaA"), + babl_type ("u8"), + babl_component ("Ya"), + babl_component ("A"), + NULL); + Babl *g8 = babl_format_new ( + babl_model ("Y"), + babl_type ("u8"), + babl_component ("Y"), + NULL); + Babl *yuv8 = babl_format_new ( + "name", "Y'CbCr u8", + babl_model ("Y'CbCr"), + babl_type ("u8-luma"), + babl_component ("Y'"), + babl_type ("u8-chroma"), + babl_component ("Cb"), + babl_component ("Cr"), + NULL); + Babl *yuvF = babl_format_new ( + babl_model ("Y'CbCr"), + babl_type ("float"), + babl_component ("Y'"), + babl_type ("float"), + babl_component ("Cb"), + babl_component ("Cr"), + NULL); + Babl *yuvaF = babl_format_new ( + babl_model ("Y'CbCrA"), + babl_type ("float"), + babl_component ("Y'"), + babl_type ("float"), + babl_component ("Cb"), + babl_component ("Cr"), + babl_component ("A"), + NULL); + +#define o(src,dst) \ + babl_conversion_new (src, dst, "linear", conv_##src##_##dst, NULL) + + o (rgbaF, rgba8); + o (rgba8, rgbaF); + o (rgbaF, rgba16); + o (rgba16, rgbaF); + o (rgbAF, rgbA8); + o (rgbA8, rgbAF); + o (rgbAF, rgbA16); + o (rgbA16, rgbAF); + o (rgbF, rgb8); + o (rgb8, rgbF); + o (rgbF, rgb16); + o (rgb16, rgbF); + o (rgba8, rgba16); + o (rgba16, rgba8); + o (rgbA8, rgbA16); + o (rgbA16, rgbA8); + o (rgb8, rgb16); + o (rgb16, rgb8); + o (gaF, ga8); + o (gAF, gA8); + o (gF, g8); + o (ga8, gaF); + o (gA8, gAF); + o (g8, gF); + o (gaF, ga16); + o (gAF, gA16); + o (gF, g16); + o (ga16, gaF); + o (gA16, gAF); + o (g16, gF); + o (ga16, ga8); + o (g16, g8); + o (rgbaF, rgbAF); + o (rgbAF, rgbaF); + o (yuv8, rgb8); + o (rgb8, yuv8); + o (yuvF, rgbF); + o (rgbF, yuvF); + o (yuvaF, rgbaF); + o (rgbA8, rgbA16); + o (rgb8, rgb16); + o (ga8, ga16); + o (gA8, gA16); + o (g8, g16); + o (rgba8, rgbaF); + o (rgbA8, rgbAF); + o (rgb8, rgbF); + o (ga8, gaF); + o (gA8, gAF); + o (g8, gF); + o (rgba16, rgbaF); + o (rgbA16, rgbAF); + o (rgb16, rgbF); + o (ga16, gaF); + o (gA16, gAF); + o (g16, gF); + o (rgbaF, rgbAF); + o (rgbAF, rgbaF); + o (gaF, gAF); + o (gAF, gaF); + o (rgbaF, rgbF); + o (rgbAF, rgbF); + o (gaF, gF); + o (gAF, gF); + o (rgbF, rgbaF); + o (rgbF, rgbAF); + o (gF, gaF); + o (gF, gAF); + o (rgbF, gF); + o (gF, rgbF); + o (rgbaF, gaF); + o (gaF, rgbaF); + o (rgbAF, gAF); + o (gAF, rgbAF); + o (rgbaF, rgb8); + o (rgbA8, rgbaF); + o (rgbA8, rgbAF); + o (ga8, gaF); + o (gA8, gAF); + o (rgbA8, rgba8); + o (rgba8, rgbA8); + o (rgbA16, rgba16); + o (gAF, rgbAF); + o (rgbaF, g8); + o (rgbaF, rgb16); + o (rgb8, rgba8); + o (rgb8, rgbA8); + o (rgbA8, rgb8); + o (rgba8, rgb8); + o (rgbaF, rgbA8); + o (rgbaF, rgbA16); + o (rgbA16, rgbaF); + o (yuv8, rgb8); + o (rgb8, yuv8); + o (yuvF, rgbF); + o (rgbF, yuvF); + o (yuvaF, rgbaF); + o (rgbaF, yuvaF); +#if 0 + o (rgbF, xyzF); + o (xyzF, rgbF); + o (labF, xyzF); + o (xyzF, labF); +#endif + + return 0; +} -- 2.30.2